package nba2kmodtool.filedesc;

import java.io.File;
import java.io.IOException;

import nba2kmodtool.util.ByteFileReader;

class N2kCdfFileReader {
	private static final boolean IS_DEBUG = BaseIffFile.IS_DEBUG;

	private BaseIffFile iff;

	N2kCdfFileReader(BaseIffFile iff) {
		this.iff = iff;
	}

	/**
	 * Read IFF type 2 (index in *.CDF file)
	 * @param in
	 * @throws IOException
	 */
	BaseIffFile read(ByteFileReader in) throws IOException {
		iff.isIndex = true;
		iff.headerSize = in.read4BytesAsInt();
		iff.fileSize = in.readBytesAsLong(8, true);
		iff.fileBlockNum = in.read4BytesAsInt();
		in.skipBytes(0x04);
		iff.fileNum = in.read4BytesAsInt();
		long next0 = in.getFilePointer() + in.read4Bytes() - 1;
		long next1 = in.getFilePointer() + in.read4BytesAsInt() - 1;
		long next2 = in.getFilePointer() + in.read4BytesAsInt() - 1;
		in.seek(next2);
		if (IS_DEBUG) {
			System.out.printf("headSize:%X, fileSize:%X, fileBlockNum:%d, fileNum:%d\n", iff.headerSize, iff.fileSize,
					iff.fileBlockNum, iff.fileNum);
		}
		int len = (int) (iff.fileSize - next2) / 2 - 1;
		byte[] buffer = new byte[len];
		for (int i = 0; i < len; i++) {
			buffer[i] = in.readByte();
			in.skipBytes(0x01);
		}
		String cdfName = new String(buffer);
		cdfName = iff.file.getPath().replaceAll(iff.file.getName(), "") + cdfName;
		iff.cdfFile = new File(cdfName);
		ByteFileReader cdf = new ByteFileReader(iff.cdfFile, "r");
		int fileNum = iff.fileNum;
		in.seek(next0 + fileNum * 4);
		iff.dataFiles = new IffDataFile[fileNum];
		for (int i = 0; i < fileNum; i++) {
			iff.dataFiles[i] = new IffDataFile();
			iff.dataFiles[i].fileSerial = in.read4Bytes();
			iff.dataFiles[i].fileType = in.read4Bytes();
			iff.dataFiles[i].partNum = in.read4BytesAsInt();
			iff.dataFiles[i].partAddr = new long[iff.dataFiles[i].partNum];
			iff.dataFiles[i].partSize = new long[iff.dataFiles[i].partNum];
			in.skipBytes(0x04 * iff.dataFiles[i].partNum);
		}
		iff.blocks = new IffBlock[fileNum * 2];
		int index = 0;
		for (int i = 0; i < iff.fileNum; i++) {
			in.seek(next1 + 4 * iff.fileNum + i * 8 * iff.dataFiles[i].partNum);
			for (int j = 0; j < iff.dataFiles[i].partNum; j++) {
				IffBlock block = new IffBlock();
				iff.dataFiles[i].partAddr[j] = in.read4Bytes();
				iff.dataFiles[i].partSize[j] = in.read4Bytes();
				block.blockAddr = iff.dataFiles[i].partAddr[j];
				block.compressedSize = iff.dataFiles[i].partSize[j];
				iff.blocks[index] = block;
				index++;
				if (j > 0 && iff.dataFiles[i].partAddr[j] < iff.dataFiles[i].partAddr[j - 1]) {
					throw new IOException("UnSupport CDF File");
				}
				/*if (IS_DEBUG) {
					System.out.printf("cur:%X - Read FileIndx:%d-%d: addr:%X-size:%X\n", in.getFilePointer(), i, j,
							block.blockAddr, block.compressedSize);
				}*/
			}
		}
		index = 0;
		for (int i = 0; i < iff.fileNum; i++) {
			for (int j = 0; j < iff.dataFiles[i].partNum; j++) {
				cdf.seek(iff.dataFiles[i].partAddr[j]);
				String compressType = cdf.readBytesAsString(4);
				long tempSize1 = cdf.readBytesAsLong(4, true);
				long tempSize2 = cdf.readBytesAsLong(4, true);
				long numb4 = cdf.readBytesAsLong(4, true);
				if (IS_DEBUG) {
					System.out
							.printf("Decompress: Cur:%X, Block:%d, CompressType:%s, CompressSize:%d, decompressSize:%d, UnkownNum:%d\n",
									in.getFilePointer(), i, compressType, tempSize2, tempSize1, numb4);
				}
				IffBlock block = iff.blocks[index];
				if (N2kIffFileDecompress.ZLIB_COMPRESS.equals(compressType)) {
					block.isCompressed = true;
					block.blockSize = tempSize1;
					iff.dataFiles[i].partSize[j] = block.blockSize;
					iff.isCompressed = true;
				} else if (N2kIffFileDecompress.isH7Compress(compressType)) {
					block.isCompressed = true;
					block.blockSize = tempSize1;
					iff.dataFiles[i].partSize[j] = block.blockSize;
					if (iff.blocks[index].compressedSize != iff.blocks[index].blockSize) {
						if (index > 0) {
							block.blockAddr = iff.blocks[index - 1].blockAddr + iff.blocks[index - 1].blockSize;
							iff.dataFiles[i].partAddr[j] = block.blockAddr;
						}
						iff.isCompressed = true;
					}
				} else {
					block.blockSize = iff.blocks[index].compressedSize;
				}
				index++;
			}
		}
		cdf.close();
		return iff;
	}
}
